package Data::Conveyor::Service::Result::Tabular;

# $Id: Tabular.pm 13653 2007-10-22 09:11:20Z gr $

use strict;
use warnings;
use Text::Table;
use Data::Miscellany 'trim';


our $VERSION = '0.02';


use base 'Data::Conveyor::Service::Result';


__PACKAGE__->mk_array_accessors(qw(headers rows));


sub result_as_string {
    my $self = shift;
    unless ($self->rows_count) {
        return "No results\n";
    }
    my @fields = $self->headers;
    my $table = Text::Table->new(@fields);
    $table->load($self->rows);
    $table;
}


# Given a LoH (list of hashes, a typical DBI result set), it populates the
# result object with those rows. It can also be a list of objects if those
# objects have methods that correspond to the headers.

sub set_from_rows {
    my ($self, %args) = @_;
    my ($did_set_headers, $count);
    my $limit  = $args{limit} if defined $args{limit};
    my @fields = @{$args{fields}} if defined $args{fields};

    for my $row (@{$args{rows}}) {
        last if defined($limit) && ++$count > $limit;
        unless ($did_set_headers) {
            scalar @fields or @fields = sort keys %$row;
            $self->headers(@fields);
            $did_set_headers++;
        }

        my @values;
        for (@fields) {
            if (ref $row eq 'HASH') {
                push @values => $row->{$_};
            } elsif (UNIVERSAL::can($row, $_)) {
                push @values => $row->$_;
            } else {
                throw Error::Hierarchy::Internal::CustomMessage(
                    custom_message => "can't set field [$_] from row [$row]"
                );
            }
        }

        $self->rows_push([ map { defined($_) ? $_ : '' } @values ]);
    }

    $self;
}


sub result { $_[0]->rows }


sub result_as_list_of_hashes {
    my $self = shift;
    my @result;
    my @headers = $self->headers; # don't call this accessor for every row

    for my $row_ref ($self->rows) {
        my $index = 0;
        my %row_hash;
        for my $header (@headers) {
            $row_hash{$header} = $row_ref->[$index++];
        }
        push @result => \%row_hash;
    }
    wantarray ? @result : \@result;
}


1;


__END__

{% USE p = PodGenerated %}

=head1 NAME

{% p.package %} - stage-based conveyor-belt-like ticket handling system

=head1 SYNOPSIS

    {% p.package %}->new;

=head1 DESCRIPTION

None yet. This is an early release; fully functional, but undocumented. The
next release will have more documentation.

=head1 METHODS

=over 4

{% p.write_methods %}

=back

{% p.write_inheritance %}

{% PROCESS standard_pod %}

=cut

